/*
*  gclist.c - UI Contact list functions
*  Copyright (c) 2005 Derek Ingrouville (dergro@users.sourceforge.net)
*
*  This program is free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Library General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

#include <string.h>
#include "gclist.h"
#include "gconvo.h"
#include "gdialog.h"
#include "eventproc.h"
#include "msn/contactlist.h"

void draw_clist (GCList *gclist);

/* How to display each row */
void gclist_cell_renderer_cb (GtkTreeViewColumn *col,
			      GtkCellRenderer *renderer,
			      GtkTreeModel *model,
			      GtkTreeIter *iter,
			      gpointer user_data);

/* Sorts contact by status, groups by name */
int gclist_sort_cb (GtkTreeModel *model,
		    GtkTreeIter *a,
		    GtkTreeIter *b,
		    gpointer userdata);

static gboolean row_selected_cb (GtkTreeSelection *selection,
				 GtkTreeModel *model,
			         GtkTreePath *path,
				 gboolean *path_currently_selected,
				 GCList *gclist);


void contact_popup_menu_send_im (GtkWidget *menuitem, GCList *gclist);
void contact_popup_menu_block (GtkWidget *menuitem, GCList *gclist);
void contact_popup_menu_delete (GtkWidget *menuitem, GCList *gclist);

void group_popup_menu_rename (GtkWidget *menuitem, GCList *gclist);
void group_popup_menu_delete (GtkWidget *menuitem, GCList *gclist);
void group_popup_menu_create (GtkWidget *menuitem, GCList *gclist);

/* Row is double clicked */
static void row_activated_cb (GtkTreeView *treeview,
			      GtkTreePath *path,
			      GtkTreeViewColumn *col,
			      GCList *gclist);

static gboolean button_press_cb (GtkWidget *treeview,
				 GdkEventButton *event,
				 GCList *gclist);

static gboolean popup_menu_cb (GtkWidget *treeview, GCList *gclist);

GCList *
gclist_new (GMainWindow *gmain)
{
	GCList *gclist;

	g_return_val_if_fail (gmain != NULL, NULL);

	gclist = g_new (GCList, 1);
	gclist->gmain = gmain;
	gclist->show_empty_groups = TRUE;
	gclist->show_offline_contacts = FALSE;
	gclist->popup_contact = NULL;
	gclist->popup_group = NULL;

	draw_clist (gclist);

	return gclist;
}

void
gclist_reset (GCList *gclist)
{
	g_return_if_fail (gclist != NULL);

	gtk_tree_store_clear (GTK_TREE_STORE (gclist->model));
}

void
gclist_free (GCList *gclist)
{
	/* TODO: Free members..... */
	g_object_unref (gclist->scrolled_window);

	gtk_object_destroy (gclist->popup_contact);
	gtk_object_destroy (gclist->popup_group);

	g_free (gclist);
	return;
}

static void
draw_contact_popup_menu (GCList *gclist)
{
	GtkWidget *menu;
	GtkWidget *menuitem;

	menu = gtk_menu_new();

	menuitem = gtk_menu_item_new_with_label ("Send an Instant Message");
	gtk_menu_shell_append (GTK_MENU_SHELL(menu), menuitem);
	g_signal_connect(menuitem, "activate", (GCallback) contact_popup_menu_send_im, gclist);

	menuitem = gtk_menu_item_new_with_label ("Block Contact");
	gtk_menu_shell_append (GTK_MENU_SHELL(menu), menuitem);
	g_signal_connect(menuitem, "activate", (GCallback) contact_popup_menu_block, gclist);

	menuitem = gtk_menu_item_new_with_label ("Delete Contact");
	gtk_menu_shell_append (GTK_MENU_SHELL(menu), menuitem);
	g_signal_connect(menuitem, "activate", (GCallback) contact_popup_menu_delete, gclist);

	gtk_widget_show_all(menu);

	gclist->popup_contact = menu;
}

static void
draw_group_popup_menu (GCList *gclist)
{
	GtkWidget *menu;
	GtkWidget *menuitem;

	menu = gtk_menu_new();

	menuitem = gtk_menu_item_new_with_label ("Rename Group");
	gtk_menu_shell_append (GTK_MENU_SHELL(menu), menuitem);
	g_signal_connect(menuitem, "activate", (GCallback) group_popup_menu_rename, gclist);

	menuitem = gtk_menu_item_new_with_label ("Delete Group");
	gtk_menu_shell_append (GTK_MENU_SHELL(menu), menuitem);
	g_signal_connect(menuitem, "activate", (GCallback) group_popup_menu_delete, gclist);

	menuitem = gtk_menu_item_new_with_label ("Create New Group");
	gtk_menu_shell_append (GTK_MENU_SHELL(menu), menuitem);
	g_signal_connect(menuitem, "activate", (GCallback) group_popup_menu_create, gclist);

	gtk_widget_show_all(menu);

	gclist->popup_group = menu;
}

void
draw_clist (GCList *gclist)
{
	GtkScrolledWindow *swindow;
	GtkTreeView *view;
	GtkTreeStore *model;
	GtkTreeViewColumn *col;
	GtkCellRenderer *renderer;
	GtkTreeSortable *sortable;
	GtkTreeSelection *selection;

	g_return_if_fail (gclist != NULL);

	/* Create view and model */
	view = (GtkTreeView *) gtk_tree_view_new ();
	model = gtk_tree_store_new (NUM_COLS,
		G_TYPE_STRING,   /*  Passport     */
		G_TYPE_STRING,   /*  Nickname     */
		G_TYPE_STRING,   /*  Groupname    */
		G_TYPE_STRING,   /*  Group GUID   */
		G_TYPE_UINT,     /*  Status       */
		G_TYPE_BOOLEAN); /*  Is Contact   */

	/*  Nickname column */
	col = gtk_tree_view_column_new ();
	gtk_tree_view_append_column (GTK_TREE_VIEW (view), col);
	renderer = gtk_cell_renderer_text_new ();
	gtk_tree_view_column_pack_start (col, renderer, TRUE);
	/* set 'text' property of the cell renderer */
	g_object_set (renderer, "text", NULL, NULL);
	/* Set a renderer function for nickname column */
	gtk_tree_view_column_set_cell_data_func (col,
		renderer,
		gclist_cell_renderer_cb,
		gclist,
		NULL);

	/* We don't want to see column header */
	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view), FALSE);

	/* Create the scrolled window */
	swindow = (GtkScrolledWindow *) gtk_scrolled_window_new (NULL, NULL);
	gtk_scrolled_window_set_policy (swindow,
		GTK_POLICY_AUTOMATIC,
		GTK_POLICY_AUTOMATIC);

	/* Sorting stuff */
	sortable = GTK_TREE_SORTABLE (model);
	gtk_tree_sortable_set_sort_func (sortable, COL_STATUS, gclist_sort_cb, NULL, NULL);
	gtk_tree_sortable_set_sort_column_id (sortable, COL_STATUS, GTK_SORT_ASCENDING);

	/* Connect view and model */
	gtk_tree_view_set_model (GTK_TREE_VIEW (view), (GtkTreeModel *) model);
	gtk_tree_selection_set_mode (gtk_tree_view_get_selection
		(GTK_TREE_VIEW (view)),
		GTK_SELECTION_SINGLE);

	/* Only one row can be selected at a time */
	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
	gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);

	/* Pack the view into the scrolled window */
	gtk_container_add (GTK_CONTAINER (swindow), (GtkWidget *) view);

	/* Function to call when row is selected */
	/*gtk_tree_selection_set_select_function (selection, row_selected_cb, gclist, NULL);*/

	draw_contact_popup_menu (gclist);
	draw_group_popup_menu (gclist);

	g_signal_connect(view,
		"row-activated",
		G_CALLBACK (row_activated_cb), 
		gclist);

	g_signal_connect(view,
		"button-press-event",
		G_CALLBACK (button_press_cb),
		gclist);
	g_signal_connect(view,
		"popup-menu",
		G_CALLBACK (popup_menu_cb),
		gclist);

	/* So we can use later */
	g_object_ref (swindow);

	gclist->scrolled_window = swindow;
	gclist->view = view;
	gclist->model = (GtkTreeModel *) model;

	gtk_widget_show_all ((GtkWidget *) swindow);
}

void
gclist_start_convo (GCList *gclist)
{
	GtkTreeSelection *selection;
	GConvo *convo = NULL;
	gchar *passport = NULL;
	MsnStatus status = OFFLINE;
	GtkTreeIter iter;

	g_return_if_fail (gclist != NULL);

	/* Get the currently selected row */
	selection = gtk_tree_view_get_selection (gclist->view);

	/* Get iter for the currently selected row */
	if (!gtk_tree_selection_get_selected (selection, &gclist->model, &iter))
		return;

	gtk_tree_model_get (gclist->model, &iter, COL_PASSPORT, &passport, -1);
	gtk_tree_model_get (gclist->model, &iter, COL_STATUS, &status, -1);

	if (passport != NULL && status != OFFLINE) {
		convo = gconvo_new (gclist->gmain->active->session, SWITCHBOARD_CHAT_NEW);
		gconvo_set_window_closed_cb (convo, gmain_window_convo_closed, gclist->gmain);
		gmain_window_add_convo (gclist->gmain, convo);
		gconvo_invite_participant (convo, passport);
		gconvo_show (convo);
	}

	g_free (passport);
}

void
contact_popup_menu_send_im (GtkWidget *menuitem, GCList *gclist)
{
	g_return_if_fail (gclist != NULL);
	gclist_start_convo (gclist);
}

void
contact_popup_menu_block (GtkWidget *menuitem, GCList *gclist)
{
	
}

void
contact_popup_menu_delete (GtkWidget *menuitem, GCList *gclist)
{
	
}

void
group_popup_menu_rename (GtkWidget *menuitem, GCList *gclist)
{
}

void
group_popup_menu_delete (GtkWidget *menuitem, GCList *gclist)
{
	GtkTreeSelection *selection;
	GtkTreeIter iter;
	gchar *group_guid = NULL;
	gint result = 0;
	gchar *warning;

	g_return_if_fail (gclist != NULL);

	/* Get the currently selected row */
	selection = gtk_tree_view_get_selection (gclist->view);

	/* Get iter for the currently selected row */
	if (!gtk_tree_selection_get_selected (selection, &gclist->model, &iter))
		return;

	if (gclist_row_is_contact (gclist->model, &iter))
		return;

	gtk_tree_model_get (gclist->model, &iter, COL_GROUPGUID, &group_guid, -1);
	g_return_if_fail (group_guid == NULL);

	warning = "Are you sure you would like to delete this group? All contacts in the group will be removed";
	/* TODO: not working if group contains contacts.. ERROR from server */

	result = vobri_display_yesno (NULL, warning);
	if (result == GTK_RESPONSE_NO)
		return;

	msn_remove_group (gclist->gmain->active->session, group_guid);
}

void
group_popup_menu_create (GtkWidget *menuitem, GCList *gclist)
{
	GGroupAddDialog *groupdialog = NULL;
	gchar *groupname = NULL;
	int ret = 0;

	g_return_if_fail (gclist != NULL);

	groupdialog = group_add_dialog_new ();
	groupname = group_add_dialog_run (groupdialog);
	group_add_dialog_free (groupdialog);

	if (groupname == NULL)
		return;
	else if (strlen (groupname) == 0) {
		g_free (groupname);
		return;
	}

	/* TODO: Input validation !! */

	ret = msn_add_group (gclist->gmain->active->session ,groupname);

	g_free (groupname);
	g_return_if_fail (ret >= 0);
}

gboolean
gclist_row_is_contact (GtkTreeModel *model, GtkTreeIter *iter)
{
	gboolean contact;
	gboolean ret = FALSE;
	unsigned int status = 0;

	g_return_val_if_fail (model != NULL, 0);
	g_return_val_if_fail (iter != NULL, 0);

	gtk_tree_model_get (model, iter, COL_ISCONTACT, &contact, -1);

	return contact;
}

gboolean
gclist_find_group (GtkTreeModel *model, gchar *guid, GtkTreeIter *dest_iter)
{
	GtkTreeIter iter;

	g_return_val_if_fail (model != NULL, FALSE);
	g_return_val_if_fail (dest_iter != NULL, FALSE);
	/*g_assert (guid != NULL);*/

	/* check if there are contacts in the group */
	if (!gtk_tree_model_get_iter_first  (model, &iter))
		return FALSE;


	/* Find the contact */
	do {
		gchar *col_guid = NULL;

		gtk_tree_model_get (model, &iter, COL_GROUPGUID, &col_guid, -1);

		if (col_guid != NULL && !strcmp (guid, col_guid)) {
			*dest_iter = iter;
			return 1;
		}
	} while (gtk_tree_model_iter_next (model, &iter));

	return 0;
}

gboolean
gclist_group_find_contact (GtkTreeModel *model,
			   const char *passport,
			   GtkTreeIter *group_iter,
			   GtkTreeIter *dest_iter)
{
	GtkTreeIter child;

	g_return_val_if_fail (model != NULL, FALSE);
	g_return_val_if_fail (passport != NULL, FALSE);
	g_return_val_if_fail (group_iter != NULL, FALSE);
	g_return_val_if_fail (dest_iter != NULL, FALSE);

	/* check if there are contacts in the group */
	if (!gtk_tree_model_iter_children (model, &child, group_iter))
		return FALSE;

	/* Find the contact */
	do {
		/*if (gclist_row_is_contact (model, &child, passport)) {*/
		if (gclist_row_is_contact (model, &child)) {
			*dest_iter = child;
			return 1;
		}
	} while (gtk_tree_model_iter_next (model, &child));

	return 0;
}

gchar *
get_string_from_status (MsnStatus status)
{
	gchar *text = NULL;

	switch (status) {
		case ONLINE:
			text = g_strdup ("Online");
			break;
		case BUSY:
			text = g_strdup ("Busy");
			break;
		case IDLE:
			text = g_strdup ("Idle");
			break;
		case BRB:
			text = g_strdup ("Be Right Back");
			break;
		case AWAY:
			text = g_strdup ("Away");
			break;
		case PHONE:
			text = g_strdup ("On the phone");
			break;
		case LUNCH:
			text = g_strdup ("Out to lunch");
			break;
		case HIDDEN:
			text = g_strdup ("Appear Offline");
			break;
		case OFFLINE:
			text = g_strdup ("Offline");
			break;
	}

	return text;
}

int
gclist_add_group (GCList *gclist, MsnGroup *group)
{
	GtkTreeIter iter;
	char *name = NULL;

	g_return_val_if_fail (gclist != NULL, -1);
	g_return_val_if_fail (group != NULL, -1);
	g_return_val_if_fail (gclist->model != NULL, -1);

	/* Check if this already have this group */
	if (gclist_find_group (gclist->model, group->guid, &iter)) {
		/* Group already exists */
		return 0;
	}

	gtk_tree_store_append ((GtkTreeStore *) gclist->model, &iter, NULL);

	name = g_strdup_printf ("%s (0/0)", group->name);

	gtk_tree_store_set (GTK_TREE_STORE (gclist->model), &iter,
		COL_PASSPORT, NULL,
		COL_NICKNAME, NULL,
		COL_GROUPNAME, name,
		COL_GROUPGUID, group->guid,
		COL_STATUS, OFFLINE,
		COL_ISCONTACT, FALSE,
		-1);

	g_free (name);

	return 0;
}

int
gclist_update_group (GCList *gclist, MsnGroup *group)
{
	GtkTreeIter iter;
	char *name = NULL;
	unsigned int num_online = 0;

	g_return_val_if_fail (gclist != NULL, -1);
	g_return_val_if_fail (group != NULL, -1);
	g_return_val_if_fail (gclist->model != NULL, -1);

	if (!gclist_find_group (gclist->model, group->guid, &iter))
		return -1;

	num_online = msn_group_get_num_contacts_online (group);
	name = g_strdup_printf ("%s (%i/%i)",
		group->name,
		num_online,
		group->num_contacts);

	gtk_tree_store_set (GTK_TREE_STORE (gclist->model), &iter,
		COL_PASSPORT, NULL,
		COL_NICKNAME, NULL,
		COL_GROUPNAME, name,
		COL_GROUPGUID, group->guid,
		COL_STATUS, OFFLINE,
		COL_ISCONTACT, FALSE,
		-1);

	g_free (name);

	return 0;
}

int
gclist_remove_group (GCList *gclist, gchar *group_guid)
{
	GtkTreeIter iter;

	g_return_val_if_fail (gclist != NULL, -1);
	g_return_val_if_fail (gclist->model != NULL, -1);
	g_return_val_if_fail (group_guid >= 0, -1);
	
	/* TODO: all contacts will be removed when a group is deleted */

	if (!gclist_find_group (gclist->model, group_guid, &iter))
		return -1;

	if (gtk_tree_store_remove (GTK_TREE_STORE (gclist->model), &iter))
		return 0;

	return -1;
}

int
gclist_add_contact (GCList *gclist, MsnContact *contact)
{
	GList *groups = NULL;
	GtkTreeIter group_iter;
	GtkTreeIter contact_iter;

	g_return_val_if_fail (gclist != NULL, -1);
	g_return_val_if_fail (contact != NULL, -1);
	g_return_val_if_fail (gclist->model != NULL, -1);

	/* Add the contact to all groups in which it belongs */
	groups = contact->groups;
	while (groups != NULL) {
		MsnGroup *group = NULL;
		gchar *status_text = NULL;
		gchar *name = NULL;
		gchar *guid = (gchar *) groups->data;

		if (!gclist_find_group (gclist->model, guid, &group_iter))
			return -1;

		group = msn_clist_find_group (gclist->gmain->active->session->clist, guid);
		g_assert (group != NULL);

		status_text = get_string_from_status (contact->status);
		name = g_strdup_printf ("%s (%s)", contact->nickname, status_text);

		if (contact->status != OFFLINE)
			if (g_strrstr (name, "Offline")) {
					g_print ("FUCK\n");
					if (strcmp (name,"Tommy (Offline)") == 0)
						g_print ("DOUBLE FUCK\n");
			}

		gtk_tree_store_append((GtkTreeStore *) gclist->model, &contact_iter, &group_iter);
		gtk_tree_store_set ((GtkTreeStore *) gclist->model, &contact_iter,
			COL_PASSPORT, contact->passport,
			COL_NICKNAME, name,
			COL_GROUPNAME, NULL,
			COL_GROUPGUID, "\0", /*TODO: check if this is an appropriate assignment */
			COL_STATUS, contact->status,
			COL_ISCONTACT, TRUE,
			-1);

		/* Update number of contacts displayed in the group */
		msn_event_add (gclist->gmain->active->session->notif->conn->events,
			"group_info_changed", 
			group);

		g_free (status_text);
		g_free (name);
		groups = g_list_next (groups);
	}

	return 0;
}

int
gclist_update_contact (GCList *gclist, MsnContact *contact)
{
	GList *list = NULL;
	GtkTreeIter group_iter;
	GtkTreeIter iter;

	g_return_val_if_fail (gclist != NULL, -1);
	g_return_val_if_fail (contact != NULL, -1);
	g_return_val_if_fail (gclist->model != NULL, -1);

	/* Updated details of this contact in all groups */
	list = contact->groups;
	while (list != NULL) {
		MsnGroup *group = NULL;
		gchar *guid = (gchar *) list->data;

		if (!gclist_find_group (gclist->model, guid, &group_iter))
			return -1;

		group = msn_clist_find_group (gclist->gmain->active->session->clist, guid);
		g_assert (group != NULL);

		if (gclist_group_find_contact (gclist->model,
			contact->passport,
			&group_iter,
			&iter)) 
		{
			gchar *status_text = NULL;
			gchar *name = NULL;

			status_text = get_string_from_status (contact->status);
			name = g_strdup_printf ("%s (%s)", contact->nickname, status_text);

			if (contact->status != OFFLINE)
			if (g_strrstr (name, "Offline")) {
					g_print ("FUCK\n");
					if (strcmp (name,"Tommy (Offline)") == 0)
						g_print ("DOUBLE FUCK\n");
			}

			gtk_tree_store_set ((GtkTreeStore *) gclist->model, &iter,
				COL_NICKNAME, name,
				COL_STATUS, contact->status,
				-1);

			g_free (status_text);
			g_free (name);
		}

		msn_event_add (gclist->gmain->active->session->notif->conn->events,
			"group_info_changed", 
			group);

		list = g_list_next (list);
	}

	return 0;
}

void
gclist_set_show_offline_contacts (GCList *gclist, gboolean show_offline)
{
	g_return_if_fail (gclist != NULL);

	gclist->show_offline_contacts = show_offline;
}

void
gclist_set_show_empty_groups (GCList *gclist, gboolean show_empty)
{
	g_return_if_fail (gclist != NULL);

	gclist->show_empty_groups = show_empty;
}

/* Callbacks */
int
gclist_sort_cb (GtkTreeModel *model,
		GtkTreeIter *a,
		GtkTreeIter *b,
		gpointer userdata)
{
	char *name1 = NULL, *name2 = NULL;
	unsigned int tmp1, tmp2;
	int ret = 0;

	gtk_tree_model_get(model, a, COL_GROUPNAME, &name1, -1);
	gtk_tree_model_get(model, b, COL_GROUPNAME, &name2, -1);
	gtk_tree_model_get(model, a, COL_STATUS, &tmp1, -1);
	gtk_tree_model_get(model, b, COL_STATUS, &tmp2, -1);

	if (name1 != NULL || name2 != NULL) {
		/* We are sorting groups */
		ret = g_utf8_collate(name1, name2);
		g_free(name1);
		g_free(name2);
	}
	else {
		/* We are sorting contacts */
		if (tmp1 != tmp2)
			ret = (tmp1 > tmp2) ? 1 : -1;
	}

	return ret;
}

void 
gclist_cell_renderer_cb (GtkTreeViewColumn *col,
			 GtkCellRenderer *renderer,
			 GtkTreeModel *model,
			 GtkTreeIter *iter,
			 gpointer user_data)
{
	GCList *gclist = NULL;
	gboolean is_contact;

	gclist = (GCList *) user_data;
	g_return_if_fail (gclist != NULL);

	gtk_tree_model_get (model, iter,
		COL_ISCONTACT, &is_contact,
		-1);

	if (is_contact)
	{
		/* We are dealing with a contact */
		MsnContact *contact = NULL;
		gchar *passport = NULL;
		gchar *name = NULL;

		gtk_tree_model_get (model, iter, 
			COL_PASSPORT, &passport, 
			COL_NICKNAME, &name,
			-1);

		contact = msn_clist_find_contact (gclist->gmain->active->session->clist, 
			passport);
		
		/* For debugging... */
		if (contact == NULL)
			g_assert (contact != NULL);

		if (contact->status != OFFLINE)
			if (g_strrstr (name, "Offline")) {
					g_print ("FUCK\n");
					if (strcmp (name,"Tommy (Offline)") == 0)
						g_print ("DOUBLE FUCK\n");
			}

		g_object_set (renderer, "text", name,
			"weight-set", FALSE,
			"visible", TRUE,
			"foreground-set", FALSE,
			NULL);

		if (!contact->has_you) {
			/* Contact is not on your reverse list (you are not on their FL) */
			g_object_set (renderer, "foreground", "#814244",
				"foreground-set", TRUE,
				NULL);
		}

		if (contact->status == OFFLINE) {
			g_object_set (renderer, "foreground", "grey",
				"foreground-set", TRUE,
				NULL);
		}

		g_free (passport);
		g_free (name);
	} 
	else 
	{
		/* We are dealing with a group */	
		MsnGroup *group = NULL;
		gboolean show = TRUE;
		gchar *group_name = NULL;
		gchar *group_guid = NULL;

		gtk_tree_model_get (model, iter,  
			COL_GROUPGUID, &group_guid, 
			COL_GROUPNAME, &group_name,
			-1);

		group = msn_clist_find_group (gclist->gmain->active->session->clist,
			group_guid);
		g_assert (group != NULL);
		g_assert (group_name != NULL);

		if (group->num_contacts == 0)
			show = gclist->show_empty_groups;

		g_object_set (renderer, "text", group_name,
			"weight-set", TRUE,
			"weight", PANGO_WEIGHT_BOLD,
			"visible", show,
			"foreground-set", FALSE,
			NULL);
		g_free (group_name);
	}

}

static void
row_activated_cb (GtkTreeView *treeview,
		  GtkTreePath *path,
		  GtkTreeViewColumn *col,
		  GCList *gclist)
{
	g_return_if_fail (gclist != NULL);
	gclist_start_convo (gclist);
}

static gboolean
button_press_cb (GtkWidget *treeview, GdkEventButton *event, GCList *gclist)
{
	if (event->type == GDK_BUTTON_PRESS  &&  event->button == 3)
	{
		int is_contact = -1;
		GtkTreeSelection *selection = NULL;
		GtkTreeIter iter;

		selection = gtk_tree_view_get_selection (gclist->view);

		/* Select row that was clicked */
		if (gtk_tree_selection_count_selected_rows (selection)  <= 1) {
			GtkTreePath *path;
			/* Get tree path for row that was clicked */
			if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(gclist->view), 
				(gint) event->x, 
				(gint) event->y,
				&path, NULL, NULL, NULL)) {
				gtk_tree_selection_unselect_all(selection);
				gtk_tree_selection_select_path(selection, path);
				gtk_tree_path_free(path);
			}
		}

		/* Check if selected row is a group or a contact */
		if (!gtk_tree_selection_get_selected (selection, &gclist->model, &iter))
			return FALSE;

		if (gclist_row_is_contact (gclist->model, &iter)) {
			gtk_menu_popup (GTK_MENU(gclist->popup_contact), NULL, NULL, NULL, NULL,
					(event != NULL) ? event->button : 0,
					gdk_event_get_time((GdkEvent*)event));
		}
		else {
			gtk_menu_popup (GTK_MENU(gclist->popup_group), NULL, NULL, NULL, NULL,
					(event != NULL) ? event->button : 0,
					gdk_event_get_time((GdkEvent*)event));
		}
	}
	return FALSE;
}

static gboolean
popup_menu_cb (GtkWidget *treeview, GCList *gclist)
{
	/* Called when menu is popped up with the use of a mouse */

	gtk_menu_popup (GTK_MENU (gclist->popup_contact), 
			NULL, NULL, NULL, NULL, NULL, 0);

	return TRUE;
}

